<?php
/**
 * Class rail_link
 *
 * The rail_link object defines an RAIL_LINK relation to exactly one rail_object. It's also possible that the link is empty,
 * empty means no RAIL_LINK relation is set or the targeting rail_object was deleted.
 *
 * Used to set an link to an other rail_object. Provides methods to get, set or delete the link.
 *
 * If deleting the target rail_object the rail_link itself will be keep in rail. Of course the link will be removed. The
 * rail_link object only support one linked target rail_object. A call of set_link will remove all former stored RAIL_LINK
 * relations.
 *
 **
 * rail_object
 *   |
 *   + rail_link
 *
 * PHP versions 5
 * See http://www.open-rail.org for more informations.
 *
 **
 * Copyright (C)
 *
 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
 * of ERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software
 * Fundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
 *
 **
 * @author Bastian Che Schröder <bastian@open-rail.org>
 * @version 2009-09-11
 * @package rail
 */
class rail_link extends rail_object {

	/**
	 * Relations which are not writeable from outside. Outside means by calling set_relation or remove_relation method.
	 * The array contains only the name of protected relation not the object associated with the relation.
	 *
	 * @var array
	 */
	protected $protected_relations = array( RAIL_LINK_TARGET );
	
	
	/**
	 * Create a new rail_link.
	 *
	 * @exception rail_param_exception|rail_writepermission_exception
	 * @param rail_connector $pRailConnector
	 * @param rail_object $pEnvironment
	 * @param string $pName OBJ_NAME (optional)
	 * @param string $pRailObject rail_object (optional)
	 * @return rail_link
	 */
	public static function create ( $pRailConnector, $pEnvironment, $pName = 'new link', $pRailObject = null ) {
		$object = parent::create( $pRailConnector, $pEnvironment, $pName );
		$pRailConnector->send_request( "UPDATE " . $pRailConnector->mysql_table_prefix . "objects SET `type`='RAIL_LINK' WHERE `id`=" . $object->get_id() );

		// set link
		if( $pRailObject instanceof rail_object )
			$object->set_link( $pRailObject );

		return $object;
	}

	
	/**
	 * Return true if a link is set, otherwise returned false.
	 * The method has_link is an alias for get_link().
	 *
	 * @return boolean
	 */
	public function has_link () {
		// check read permission
		if( !$this->is_readable() )
		 	throw new rail_readpermission_exception( $this, $this->rail_connector->get_user() );

		try{
			return $this->get_link();
		}
		catch( rail_exception $e ){
			// more then one target in RAIL_LINK_TARGET relations are found
			return false;
		}
	}


	/**
	 * Get link target. Return a rail_object or false if no objects is set.
	 *
	 * @exception rail_readpermission_exception
	 * @return mixed
	 */
	public function get_link () {
		// check read permission
		if( !$this->is_readable() )
		 	throw new rail_readpermission_exception( $this, $this->rail_connector->get_user() );

		if( !isset( $this->cache[ RAIL_LINK_TARGET ] ) ){
			$link_relation = $this->get_relations( RAIL_LINK_TARGET );

			 // throw an exception if more then one target found
			 if( count( $link_relation ) > 1 )
			 	throw new rail_exception( $this, 'found more then one target in RAIL_LINK relation from this object.' );

			 // write rail target to cache or return false if no target is set
			 if( count( $link_relation ) > 0 )
			 	$this->cache[ RAIL_LINK_TARGET ] = $link_relation[0];
			 else
			 	return false;
		}

		return $this->cache[ RAIL_LINK_TARGET ];
	}


	/**
	 * Remove the link if a link is set.
	 *
	 * @exception rail_writepermission_exception
	 */
	public function remove_link () {
		// check write permission
		if( !$this->is_writeable() )
		 	throw new rail_writepermission_exception( $this, $this->rail_connector->get_user() );

		// remove all existing RAIL_LINK relations
		foreach( $this->get_relations( RAIL_LINK_TARGET ) as $object )
			$this->remove_relation( $object, RAIL_LINK_TARGET );
	}


	/**
	 * Set the link. Require a rail_object as target.
	 *
	 * @exception rail_writepermission_exception|rail_param_exception
	 * @param rail_object $pRailObject
	 */
	public function set_link ( $pRailObject ) {
		// check write permission
		if( !$this->is_writeable() )
		 	throw new rail_writepermission_exception( $this, $this->rail_connector->get_user() );
		// check wheater new target is a rail_object
		if( !isset($pRailObject) || !$pRailObject instanceof rail_object )
			throw new rail_param_exception( $this, 'pRailObject', $pRailObject );

		// remove all existing RAIL_LINK relations
		foreach( $this->get_relations( RAIL_LINK_TARGET ) as $object )
			$this->remove_relation( $object, RAIL_LINK_TARGET );

		// set new RAIL_LINK relation
		$this->set_relation( $pRailObject, RAIL_LINK_TARGET );
		$this->cache[ RAIL_LINK_TARGET ] = $pRailObject;
	}

} // End of rail_link
?>